package com.im;

import java.awt.Component;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorConvertOp;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;

// 图标单元格渲染者
@SuppressWarnings("serial")
class IconCellRenderer extends JLabel implements ListCellRenderer<String> {
    private final List<Icon> mGrayIconList;     // 灰色图标列表
    private final List<Icon> mIconList;         // 图标列表（含灰色图标、正常图标）
    private final List<Icon> mNormalIconList;   // 正常图标列表

    /**
     * 构造方法。
     */
    public IconCellRenderer() {
        // 初始化成员
        mGrayIconList = new ArrayList<>();
        mIconList = new ArrayList<>();
        mNormalIconList = new ArrayList<>();
        
        // 设置背景不透明
        super.setOpaque(true);
        
        // 设置图标居中显示
        super.setHorizontalAlignment(SwingConstants.CENTER);
        super.setVerticalAlignment(SwingConstants.CENTER);
    }
    
    /**
     * 添加一个图标。
     * @param iconFilePath  图标文件路径
     * @param colorful      彩色则为 true，灰色则为 false
     */
    public Icon addIcon(String iconFilePath, boolean colorful) {
        // 加载图标
        final BufferedImage image = this.loadImage(iconFilePath);

        // 添加彩色图标
        final Icon normalIcon = new ImageIcon(image);
        mNormalIconList.add(normalIcon);

        // 添加灰色图标
        final ImageIcon gradIcon = this.getGrayIcon(image);
        mGrayIconList.add(gradIcon);
        
        // 添加到图标列表
        if (colorful) {
            mIconList.add(normalIcon);
        } else {
            mIconList.add(gradIcon);
        }
        
        return normalIcon;
    }

    /**
     * 改变某个图标的颜色。
     * @param index    图标索引
     * @param colorful 彩色则为 true，灰色则为 false
     */
    public void changeColor(int index, boolean colorful) {
        final Icon image = colorful ? mNormalIconList.get(index): mGrayIconList.get(index);
        mIconList.set(index, image);
    }

    /**
     * 清除所有图标。
     */
    public void clear() {
        mGrayIconList.clear();
        mIconList.clear();
        mNormalIconList.clear();
    }

    /**
     * 获取灰色图标。
     * @param image 图标
     * @return 灰色图标
     */
    private ImageIcon getGrayIcon(BufferedImage image) {
        final BufferedImage grayImage = new BufferedImage(image.getWidth(), image.getHeight(), image.getType());
        final ColorSpace grayCS = ColorSpace.getInstance(ColorSpace.CS_GRAY);
        final ColorConvertOp convertor = new ColorConvertOp(grayCS, null);
        convertor.filter(image, grayImage);
        return new ImageIcon(grayImage);
    }
    
    /**
     * 获取列表中的某个表项。
     * @param list          列表
     * @param text          表项文字
     * @param index         表项索引，从零开始
     * @param isSelected    该表项被选中则为 true，否则为 false
     * @return 表项
     */
    @Override
    public Component getListCellRendererComponent(JList<? extends String> list, String text, int index, boolean isSelected, boolean arg4) {
        // 设置文字
        if (!text.isEmpty()) {
            super.setText(text);
        }

        // 设置图标
        if (mIconList.size() > 0) {
            final Icon icon = mIconList.get(index);
            if (icon != null) {
                super.setIcon(icon);
            }
        }

        // 设置选中时的背景色
        if (isSelected) {
            super.setBackground(list.getSelectionBackground());
            super.setForeground(list.getSelectionForeground());
        } else {
            super.setBackground(list.getBackground());
            super.setForeground(list.getForeground());
        }

        return this;
    }
    
    /**
     * 加载图片。
     * @param iconFilePath  图片文件路径
     * @return 图片
     */
    private BufferedImage loadImage(String iconFilePath) {
        // 加载图标
        BufferedImage image = null;
        File file;
        try {
            file = new File(iconFilePath);
            image = ImageIO.read(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return image;
    }
}

// 用户列表视图
@SuppressWarnings("serial")
class UserListView extends JList<String> {
    private final IconCellRenderer mIconList;           // 图标列表
    private final DefaultListModel<String> mTextList;   // 文字列表
    private int mIconHorizontalSpacing;                 // 图标横向间距
    private int mIconVerticalSpacing;                   // 图标纵向间距

    /**
     * 构造方法。
     */
    public UserListView() {
        // 初始化成员
        mIconList = new IconCellRenderer();
        mTextList = new DefaultListModel<>();
        mIconHorizontalSpacing = 0;
        mIconVerticalSpacing = 0;
        
        // 设置每行的内容提供者
        super.setCellRenderer(mIconList);

        // 设置字符串提供者
        super.setModel(mTextList);

        // 设置边框
        super.setBorder(BorderFactory.createEtchedBorder());

        // 设置方向
        super.setLayoutOrientation(HORIZONTAL_WRAP);
    }
    
    /**
     * 添加一个表项。
     * @param itemText  表项文字
     * @param iconIndex 图标索引
     * @param colorful  彩色则为 true，灰色则为 false
     */
    public void addItem(String itemText, int iconIndex, boolean colorful) {
        // 添加图标
        final String iconFilePath = String.format(Const.ICON_FILE_PATH, iconIndex);
        final Icon icon = mIconList.addIcon(iconFilePath, colorful);
        
        // 添加文字
        mTextList.addElement(itemText);
        
        // 设置单元格尺寸
        if (mIconHorizontalSpacing > 0) {
            final int cellWidth = icon.getIconWidth() + mIconHorizontalSpacing * 2;
            super.setFixedCellWidth(cellWidth);
        }
        if (mIconVerticalSpacing > 0) {
            final int cellHeight = icon.getIconHeight() + mIconVerticalSpacing * 2;
            super.setFixedCellHeight(cellHeight);
        }
    }

    /**
     * 改变某个表项的图标颜色。
     * @param itemText  表项的文字
     * @param colorful  彩色则为 true，灰色则为 false
     */
    public void changeItemColor(String itemText, boolean colorful) {
        // 查找表项
        final int itemIndex = mTextList.indexOf(itemText);
        if (itemIndex < 0) {
            return;
        }

        // 设置图标颜色
        mIconList.changeColor(itemIndex, colorful);
        super.repaint();
    }
    
    /**
     * 清除所有表项。
     */
    public void clear() {
        mIconList.clear();
        mTextList.clear();
    }
    
    /**
     * 设置图标的水平间距。
     * @param spacing   水平间距
     */
    public void setIconHorizontalSpacing(int spacing) {
        mIconHorizontalSpacing = spacing;
    }

    /**
     * 设置图标的垂直间距。
     * @param spacing   垂直间距
     */
    public void setIconVerticalSpacing(int spacing) {
        mIconVerticalSpacing = spacing;
    }
}
